Add Concurrency option and MPSC support using farbot.#18
Add Concurrency option and MPSC support using farbot.#18atsushieno wants to merge 5 commits intocjappl:mainfrom
Conversation
f0511b0 to
06f3f56
Compare
06f3f56 to
13f13fe
Compare
cjappl
left a comment
There was a problem hiding this comment.
Thank you for taking the time for this work!! Let's chat more about some of my comments and see what we can come up with. I like the direction it is going, but we should work out some of the bigger picture.
test/test_rtlog.cpp
Outdated
|
|
||
| SUBCASE("Enqueue more than capacity and get an error") { | ||
| const auto maxNumMessages = 10; | ||
| const auto maxNumMessages = 16; |
There was a problem hiding this comment.
Is there a reason this changed? I'm surprised
There was a problem hiding this comment.
(I'm going to bed soon-ish, so let me put quick comments only for now.)
Yes - farbot FIFO does not accept the size of buffers that is not 2^n. Probably I should put some caution on the README or the header or somewhere.
There was a problem hiding this comment.
Maybe we can enforce it via a static assert/restriction on the template param
There was a problem hiding this comment.
I don't think we use this class for now, but I have added static_assert in the MPSC wrapper constructor.
| FetchContent_MakeAvailable(ReaderWriterQueue) | ||
| endif() | ||
|
|
||
| if (NOT TARGET farbot) |
There was a problem hiding this comment.
THANK YOU for this contribution and taking the time to write it up.
I have a couple of concerns, which maybe you can help me figure out.
First, I never liked how I downloaded concurrentqueue "secretly" for the users. I think a (maybe better?) approach would be the users providing their own queue, perhaps wrapped in some External Polymorphism package like you've done here.
Now that we have two options (farbot AND concurrentqueue) we are downloading even more dependencies "secretly" for the user. It feels a little dirty, and I don't know what we should do about it.
There was a problem hiding this comment.
Perhaps one solution to this is to pass in the queue that the suer wants, but just provide two back ends that can be hidden behind some optional cmake
RTSAN_BUILD_FARBOT_BACKEND
RTSAN_BUILD_CONCURRENTQUEUE_BACKEND
There was a problem hiding this comment.
I'm completely spitballing here. I just want to make sure before we extend to 2 backends that we have a plan for when we inevitably need to add a 3rd
There was a problem hiding this comment.
I understand your concern. Once thing I would point out is that we would probably like to have those options alongside and not exclusive - one would like to have both kinds of loggers (also to avoid possible build config conflicts between sub-projects).
(BTW I didn't replace readerwriterqueue with concurrentqueue, so only farbot version is added. I can add that too if you want, but it's not going to be RT log anymore ;-) )
There was a problem hiding this comment.
I'm digging into this just a little bit and I remember one of the sticking points that prevented me from doing this in the past.
If you change the args to have a QueueType:
template <typename LogData, size_t MaxNumMessages, size_t MaxMessageLength,
std::atomic<std::size_t>& SequenceNumber, typename QueueType>
This becomes tricky because QueueType needs to depend on InternalLogData.
(I'm not sure immediately how to re-arrange to get around this problem)
|
|
||
| InternalLogData value; | ||
| while (mQueue.try_dequeue(value)) { | ||
| while (mQueue->tryDequeue(value)) { |
There was a problem hiding this comment.
My other slight concern is this use of dynamic memory here. While it is perfectly real-time safe, it is also slower (probably) than the one that holds the queue on the stack.
Is there any way to have this be template based instead of inheritance based?
There was a problem hiding this comment.
Alright. It is probably possible. We would still need those wrapper classes to make code consistent though (yet removing inheritance).
include/rtlog/rtlog.h
Outdated
| }; | ||
| class InternalQueueMPSC : public InternalQueue { | ||
| farbot::fifo<InternalLogData, farbot::fifo_options::concurrency::single, | ||
| farbot::fifo_options::concurrency::multiple> |
There was a problem hiding this comment.
Smaller comment that we should address after the bigger comments above - let's make the behavior on push/pop explicit:
fifo_options::full_empty_failure_mode::return_false_on_full_or_empty,
fifo_options::full_empty_failure_mode::overwrite_or_return_default
Are the options. I think both are wait free on write, I guess I would opt for return_false_on_full_or_empty so the user can decide what they want to do if the queue fails and data loss happens
| Concurrency == QueueConcurrency::Single_Producer_Single_Consumer | ||
| ? (std::unique_ptr<InternalQueue>) | ||
| std::make_unique<InternalQueueSPSC>() | ||
| : std::make_unique<InternalQueueMPSC>()}; |
There was a problem hiding this comment.
nit:
perhaps a case statement would be more clear and more extensible for the future
|
|
||
| constexpr auto MAX_LOG_MESSAGE_LENGTH = 256; | ||
| constexpr auto MAX_NUM_LOG_MESSAGES = 100; | ||
| constexpr auto MAX_NUM_LOG_MESSAGES = 128; |
There was a problem hiding this comment.
Yes, same as maxNumMessages.
|
@atsushieno - would you check out #19 when you get a chance? Possibly even pull it down and see if you can easily use it with farbot? This is just a draft of how this COULD work, not necessarily the final version |
|
I'm trying plain #19 without my changes, but I couldn't get this compiled on my macOS environment: I'm not sure how portable the use of those template template parameters are. (I guess it should be fairly standard?) |
|
According to my experiment at Compiler Explorer, clang earlier than 19 had this issue. clang-19 successfully compiles it. https://godbolt.org/z/o755bnvPh I guess this new template template parameters code is going to be blocking until clang-19 becomes broadly available. My xcode toolchain is not the latest 16.2 (it is 16.0) and I kinda have reason to stick to it (safe for language bindings such as kotlin-native and tooling). Maybe some other people too. edit: in xcode 16.0 the clang version is 16.0.0 (clang-1600.0.26.3) |
4ab0c94 to
1d2d9bb
Compare
1d2d9bb to
d1839e5
Compare
Yeah, we should for sure do something that works in compilers older than 19. Thanks for looking. Let me see if there is a different way to do the same thing! |
context: #6 #14
It would not be a fun task to make up a customization setup for queue backends, so I made a minimum-ish one. The behavior should be backward compatible.